﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Furion.DatabaseAccessor;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using YShop.Application.Contracts.Shop;
using YShop.Application.Contracts.Shop.Products;
using YShop.Core;
using YShop.Core.Entites.Shop;
using YShop.Core.Managers.Caches;

namespace YShop.Application.Shop
{
    /// <summary>
    /// 商品
    /// </summary>
    [ApiDescriptionSettings("Shop")]
    public class ProductService : IBaseService, IProductService
    {
        /// <summary>
        /// 商品仓储
        /// </summary>
        private readonly IRepository<Product> _repository;
        /// <summary>
        /// 缓存管理
        /// </summary>
        private readonly CacheManager _cacheManager;
        /// <summary>
        /// 商品列表
        /// </summary>
        public List<ProductDto> Products => _cacheManager.GetOrCreate(CacheKeys.Products, _ => 
        {
            return _repository.Include(s => s.Attributes, false)
                              .Include(s => s.Details)
                              .ProjectToType<ProductDto>()
                              .ToList();
        });

        public ProductService(
            IRepository<Product> repository, 

            CacheManager cacheManager)
        {
            _repository = repository;
            _cacheManager = cacheManager;
        }

        [HttpGet]
        [Route("/api/product")]
        public async Task<PagedList<ProductDto>> GetPageList([FromQuery]ProductPageSearchDto search)
        {
            return await Products.ToPageListAsync(search.PageIndex, search.PageSize);
        }

        public async Task<ProductDto> GetAsync(string id)
        {
            return await Task.FromResult(Products.FirstOrDefault(p => p.Id == id));
        }


        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="productDto"></param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task SaveFormAsync(ProductDto productDto)
        {
            var product = await _repository.Include(s => s.Attributes,false)
                                           .Include(s => s.Details)
                                           .FirstOrDefaultAsync(s=>s.Id == productDto.Id);
            if (product == null)
            {
                await _repository.InsertAsync(productDto.Adapt<Product>());
            }
            else
            {
                #region 商品属性修改
                var productAttributeRepostroy = _repository.Change<ProductAttribute>();
                var oldAttributes = new List<ProductAttribute>(product.Attributes);
                foreach (var productAttribute in productDto.Attributes)
                {
                    // 插入商品属性
                    if (!oldAttributes.Any(s => s.Id == productAttribute.Id))
                    {
                        await productAttributeRepostroy.InsertAsync(productAttribute.Adapt<ProductAttribute>());
                    }
                    else
                    {
                        // 修改
                        await productAttributeRepostroy.UpdateAsync(productAttribute.Adapt<ProductAttribute>());
                        oldAttributes.Remove(oldAttributes.First(s => s.Id == productAttribute.Id));
                    }
                }
                // 删除商品属性
                if (oldAttributes.Count > 0)
                {
                    foreach (var del in oldAttributes)
                    {
                        await productAttributeRepostroy.DeleteAsync(del.Id);
                    }
                }
                #endregion


                #region 商品明细(SKU)
                var detailRepostory = _repository.Change<ProductDetail>();
                var oldDetails = new List<ProductDetail>(product.Details);
                foreach(var detail in productDto.Details)
                {
                    detail.ProductId = product.Id;
                    var oldDetail = oldDetails.FirstOrDefault(s => s.Id == detail.Id);
                    if(oldDetail == null)
                    {
                        await detailRepostory.InsertAsync(detail.Adapt<ProductDetail>());
                    }
                    else
                    {
                        await detailRepostory.UpdateAsync(detail.Adapt<ProductDetail>(), true);
                        oldDetails.Remove(oldDetail);
                    }
                }
                if(oldDetails.Count > 0)
                {
                    foreach(var del in oldDetails)
                    {
                        await detailRepostory.FakeDeleteAsync(del);
                    }
                }
                #endregion
                productDto.Attributes = null;
                productDto.Details = null;
                await _repository.UpdateAsync(productDto.Adapt<Product>(),true);
            }

            _cacheManager.Remove(CacheKeys.Products);
        }

    }

}
